/*
 * RenderHelper.java
 *
 * Created on September 3, 2005, 8:10 PM
 *
 * To change this basis, choose Tools | Options and locate the basis under
 * the Source Creation and Management node. Right-click the basis and choose
 * Open. You can then make changes to the basis in the Source Editor.
 */

package com.xucia.jsponic.remote.browser;
import javax.servlet.http.HttpServletRequest;


/**
 *
 * @author Kris Zyp
 */
public abstract class BrowserAdapter {
/*    public static BrowserAdapter getBrowserAdapter(BrowserType type) {
    	switch (type) {
    		case WML : return new WMLAdapter(); 
    		case IE : return new IEAdapter(); 
    		case MOZILLA : return new MozillaAdapter(); 
    		case FIREFOX : return new MozillaAdapter();
    		case TEXT_BASED : return new TextBasedAdapter();             
        }
    	return null;
    }*/
    public static boolean isModern(BrowserType type) {
    	switch (type) {
			case WML : return false; 
			case IE : return true; 
			case MOZILLA : return true; 
			case OLD_MOZILLA : return false; 
			case FIREFOX : return true;
			case SAFARI : return true;
			case OPERA : return true;
			case TEXT_BASED : return false;             
	    }
		return false;
    }
    public enum BrowserType {TEXT_BASED, IE, MOZILLA, OLD_MOZILLA,FIREFOX, SAFARI,SAFARI_OLD,OPERA, WML}; 
    public static BrowserType getBrowserType(HttpServletRequest request) {
        String accept = request.getHeader("ACCEPT");
        if (null != accept && -1 != accept.indexOf("wml")) {
            return BrowserType.WML;
        }
        else {
            //System.err.println("Browser is " + request.getHeader("USER-AGENT"));
            String userAgent = request.getHeader("USER-AGENT");
            if (userAgent == null)
            	return BrowserType.TEXT_BASED;  // TODO: Change this, this was just for testing with BrowsrCamp.com
            if (userAgent.indexOf("Opera") > -1)
                return BrowserType.OPERA;
            else if (userAgent.indexOf("MSIE") > -1)
                return BrowserType.IE;
            else if (userAgent.indexOf("Firefox") > -1)
                return BrowserType.FIREFOX;
            else if (userAgent.indexOf("BigBrother") > -1) // treat big brother like a first class browser, because it is just pinging so we don't want to do any extra processing
                return BrowserType.FIREFOX;
            else if (userAgent.indexOf("Safari") > -1) {
            	int safariIndex = userAgent.indexOf("Safari");
            	try {
	            	if (Integer.parseInt(userAgent.substring(safariIndex + 7,safariIndex + 10)) > 400)
	            		return BrowserType.SAFARI;
            	}
            	catch (Exception e) {
            		System.err.println("Error determining safari build " + e.getMessage());
            	}
                return BrowserType.SAFARI_OLD;
            }
            else if (userAgent .indexOf("Gecko") > -1) {
            	if (userAgent.startsWith("Mozilla/") && 
            			Integer.parseInt(userAgent.substring("Mozilla/".length(),"Mozilla/".length()+1)) >= 5)
            		return BrowserType.MOZILLA;
            	else
            		return BrowserType.OLD_MOZILLA;
            }
            else
            	return BrowserType.TEXT_BASED;
        }
    }

    /*public static final String SAVE_VALUE_PREFIX = "_sv_";
    public static StringEncoder attributeEncoder = AttributeContext.attributeEncoder();
    public static StringEncoder inTagEncoder = AttributeContext.attributeEncoder(); // TODO: Make a inTagEncoder
    public abstract void getEditableModeStartTag(StringBuffer buf, ElementContext context,boolean editable);
    public abstract void getEditableModeEndTag(StringBuffer buf, ElementContext context,boolean editable);
    public void getStartTag(StringBuffer buf, ElementContext context) {
        buf.append("<SPAN");
        buf.append(" Id=\"" + context.getHTMLId() + "\"");
/*        if (context.contentSelectorElement)
            buf.append(" selectionId=\"" + context.source.getId() + "\"");
        if (context.tags != null) {
            Iterator<Map.Entry<String,String>> iterator = context.tags.entrySet().iterator();
            while (iterator.hasNext()) {
                Map.Entry<String,String> entry = iterator.next();
                buf.append(" " + inTagEncoder.encode(entry.getKey()) + "=\"" + attributeEncoder.encode(entry.getValue()) + "\"" );
            }
        }
        buf.append(">");
    }
    public void getEndTag(StringBuffer buf, ElementContext context) {
        buf.append("</SPAN>");
    }
    public void getEmptyTag(StringBuffer buf) {
    }
    public void setHTML(Map<String,String> parameters,HTMLPage page) {
        System.out.println("setter started");
        HashMap sequences = new HashMap(); 
        String name, value;
        Vector sequence;
        int sequenceNumber ;
        for (Entry<String,String> entry : parameters.entrySet()) {
            name = entry.getKey();;
            //System.err.println(" name " + name + " startswith " + GlobalData.SAVE_VALUE_PREFIX);
            if (name.startsWith(SAVE_VALUE_PREFIX)) {

                value = entry.getValue();
                System.out.println("value before decoding: " + value);
                name = name.substring(SAVE_VALUE_PREFIX.length());
                System.out.println("setting " + name + " = " + value );
                sequenceNumber = 1;
                if (name.matches(".+\\.\\d+"))  { // matches anything ending with a .number, this is a part of a multipart block of data
                    try {
                        sequenceNumber = Integer.parseInt(name.substring(name.lastIndexOf('.')+1)); // find the part of the period
                        name = name.substring(0,name.lastIndexOf('.')); // remove the .# prefix
                        System.out.println("A value in a sequence: " + name + " seq no: " + sequenceNumber);
                    }
                    catch (NumberFormatException e) {
                        System.out.println("invalid number after the last period, assuming it is not a numbered sequence");
                    }
                }
                sequence = (Vector) sequences.get(name);  // add each one to the sequences list
                if (sequence == null) { // if this sequence does not exist lets create it and put it in the hashmap of sequences
                    sequence = new Vector();
                    sequences.put(name,sequence);
                }
                while (sequenceNumber > sequence.size())  // we must make the vector large enough to do the set operation
                    sequence.add(" "); // just a filler
                sequence.set(sequenceNumber-1,  value); // the sequence numbers start at 1
            }  
            else 
                if (name.equals("newPage")) {
                    // what is this?
                }
        }
        Iterator sequenceIterator = sequences.keySet().iterator();
        while (sequenceIterator.hasNext()) {
            name = (String) sequenceIterator.next();
            sequence = (Vector) sequences.get(name);
            value = "";
            for (int i = 0; i < sequence.size(); i++ ) {
                value = value + sequence.get(i);
            }
            URLDecoder urlDecoder = new URLDecoder();
            System.out.println("Getting object at path " + name); 
            ElementContext element = page.getElementById(name);
            if (element == null)
                throw new RuntimeException("Unable to find element with id of " + name);
            if (element.deleted)
                throw new RuntimeException("Unable to display deleted element " + element);
            setHTML(element, value);
        }        
    }
    List parsedValues = new LinkedList();
    void addText(String value) {
        if (parsedValues.size() > 0 && parsedValues.get(parsedValues.size()-1) instanceof String)
            parsedValues.set(parsedValues.size()-1, parsedValues.get(parsedValues.size()-1) + value);
        else
            parsedValues.add(value);
    }
    protected void setHTML(ElementContext element, String value) {
        try {
//            System.err.println("parsing value: " + value);
            parsedValues.clear();
            Lexer lexer = new Lexer(value);
            Node node;
            boolean inTag = false;
            while ((node = lexer.nextNode()) != null) {
                if (node instanceof Text || node instanceof Remark) {
                    addText(node.toHtml());
                }
                else if (node instanceof Tag) {
                    Tag tag = (Tag)node;
                    if (tag.getTagName().equals("XC:ELEMENT")) { 
                        if (tag.isEndTag() && inTag) {
                        	inTag = false;
                        }
                        else if (tag.isEndTag() && !inTag) {
                        	throw new RuntimeException("encountered unexpected end of XC tag");
                        }
                        else if (!tag.isEndTag() && inTag) {
                        	throw new RuntimeException("encountered unexpected start of XC tag, the inner tag collapser probably failed");
                        } 
                        else { //(!tag.isEndTag() && !inTag)
                        	inTag = true;
	                        NewElement newElem = new NewElement();
	                        newElem.type = tag.getAttribute("newName");
	                        
	                        newElem.style = tag.getAttribute("style");
	                        if (newElem.type == null) {
	                            String id = tag.getAttribute("childid");
	                            if (id == null)
	                                id = tag.getAttribute("id");
	                            if (id != null) {
	                                ElementContext foundElement = element.getHTMLDocument().getElementById(id);
	                                if (foundElement == null)
	                                    throw new RuntimeException("Could not find child element " + id);
	                                if (newElem.style != null)
	                                    foundElement.setStyle(newElem.style);
	                                parsedValues.add(foundElement);
	                            }
	                            else {
	                                //tags are created for closing tags as well, but this is a tip off that it is a closing tag and we can ignore it
	                            }
	                        }
	                        else { 
	                            if (tag.getAttribute("xcid") != null)
	                                if (newElem.type.equals("for") || newElem.type.equals("forcontext")) {
	                                    newElem.id = new Id();
	                                    newElem.id.addField(tag.getAttribute("xcid")); // field name
	                                }
	                                else
	                                    newElem.id = new Id(tag.getAttribute("xcid"));
	                            parsedValues.add(newElem);
	                        }
                        }
                    }
                    else if (tag.getTagName().equals("XC:EMPTY")) {
                    	// just a visual placeholder
                    }
                    else if (tag.getTagName().equals("IMG") || (tag.getTagName().equals("SPAN") && "IMG".equals(tag.getAttribute("type")))) {
                        ImageHolder image = new ImageHolder();
                        for (Attribute attribute : (Vector<Attribute>) tag.getAttributesEx()) {
                            String name = attribute.getName();
                            if (name != null) {
                                String attrValue = attribute.getValue();
                                if (name.equals("src"))  {
                                    if (attrValue.startsWith("http:") && attrValue.indexOf("images") != -1) {
                                        attrValue = attrValue.substring(attrValue.indexOf("images"));
                                    }
                                    image.src=attrValue;
                                }
                                else if (name.equals("width") && image.width == -1) // only if it is not already set, the style parameter must take precedence 
                                    image.width=Integer.parseInt(attrValue .replaceAll("[^0-9]",""));
                                else if (name.equals("height") && image.height == -1) 
                                    image.height=Integer.parseInt(attrValue .replaceAll("[^0-9]",""));
                                else if (name.equals("IMG")) {                                    
                                }
                                else if (name.equals("hmode")) {                                    
                                }
                                else if (name.equals("lastMouseX")) {                                    
                                }
                                else if (name.equals("lastMouseY")) {                                    
                                }
                                else if (name.equals("style")) {                                    
                                    image.setStyle(attrValue);
                                }
                                else if (name.equals("root")) {                                    
                                }
                                else if (name.equals("vmode")) {                                    
                                }
                                else 
                                    image.tags().put(name,attrValue );
                            }
                        }
                        parsedValues.add(image);
                        if (image.width > -1) {
                            ImageManagement.submitForResizing(image);
                        }
                        
                    }
                    else
                        addText(tag.toHtml());
                }
            }
        }
        catch (ParserException e) {
            throw new RuntimeException(e);
        }
        element.setHTML(parsedValues); 
    }
    int getEditorType(ElementContext element) {
        if (element.source instanceof DataField) {
            DataObject field = ((DataField)element.source).getField();
            int editorType = 0; // start with on restrictions
            try {
	            DataObject fieldType = (DataObject) field.get("field type");
	            if (fieldType.get(GlobalData.NAME_FIELD).equals("string"))
	                editorType = 1; //
	            Object editorRestrictions = field.get("edit restrictions");
	            if (editorRestrictions instanceof Integer) {
	                editorType += ((Integer)editorRestrictions).intValue();
	            }
            }
            catch (ClassCastException e) {
            	System.err.println(e.getMessage() + " due to no available field type");
            }
            return editorType;
        }
        else 
            return 0;
    }

	public boolean canEdit() {
		return false;
	}*/
}